import logging
import re
from typing import TypeVar, Optional

from fastapi import HTTPException
from pydantic import BaseModel, validator, Field

from app.model.person import Sex

T = TypeVar("T")

# get root logger
logger = logging.getLogger(__name__)


class RegisterSchema(BaseModel):
    username: str = Field(..., description="User Name")
    password: str = Field(..., description="User password")
    phone_number: str = Field(..., description="User phone number")
    sex: Sex
    email: Optional[str] = Field(None, description="User email")
    subject_type: str = Field(..., description="Subject type")
    exam_province: str = Field(..., description="Exam province")

    # profile: str = "base64"

    # phone number validation
    @validator("phone_number")
    def phone_validation(cls, v):
        logger.debug(f"phone in 2 validatior: {v}")

        # regex phone number
        regex = r"^1[3-9]\d{9}$"
        if v and not re.search(regex, v, re.I):
            raise HTTPException(status_code=400, detail="Invalid input phone number!")
        return v

    # Sex validation
    @validator("sex")
    def sex_validation(cls, v):
        if hasattr(Sex, v) is False:
            raise HTTPException(status_code=400, detail="Invalid input sex")
        return v

    # Password validation
    @validator("password")
    def password_validation(cls, v):
        # Minimum 8 characters, at least one uppercase, one lowercase, one number and one special character
        regex = r"^(?=.*[a-z])(?=.*\d).{8,}$"
        if " " in v or not re.search(regex, v):
            raise HTTPException(
                status_code=400,
                detail="Password must have at least 8 characters, one letter, one number, and no spaces!",
            )
        return v


class LoginSchema(BaseModel):
    phone_number: str = Field(..., description="User phone number")
    password: str = Field(..., description="User password")


class ForgotPasswordSchema(BaseModel):
    phone_number: str = Field(..., description="User phone number")
    new_password: str = Field(..., description="User password")

    # Password validation
    @validator("new_password")
    def password_validation(cls, v):
        # Minimum 8 characters, at least one uppercase, one lowercase, one number and one special character
        regex = r"^(?=.*[a-z])(?=.*\d).{8,}$"

        if " " in v or not re.search(regex, v):
            raise HTTPException(
                status_code=400,
                detail="Password must have at least 8 characters, one letter, one number, and no spaces!",
            )
        return v


class DetailSchema(BaseModel):
    status: str
    message: str
    result: Optional[T] = None


class ResponseSchema(BaseModel):
    detail: str
    result: Optional[T] = None
